home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / intrfc70.zip / LOADER.PAS < prev    next >
Pascal/Delphi Source File  |  1994-03-16  |  10KB  |  395 lines

  1. unit loader;
  2. {$I SWITCHES.INC}
  3. interface
  4.  
  5.   uses util,dump,globals,head,objects,dos;
  6.  
  7. type
  8.  
  9.   hash_ptr = ^hash_rec;
  10.   hash_rec = record
  11.     byte_len : word;
  12.     table    : word_array;
  13.   end;
  14.  
  15.   list_ptr = ^list_rec;
  16.   list_rec = record
  17.     offset : word;
  18.     hash : word;
  19.     next : list_ptr;
  20.   end;
  21.  
  22.   proc_list_ptr = ^proc_list_rec;
  23.   proc_list_rec = record
  24.     entry : word;
  25.     name : pstring;
  26.     next : proc_list_ptr;
  27.   end;
  28.  
  29.   unit_ptr = ^unit_rec;
  30.   unit_rec = record
  31.     target:word;
  32.     checksum:word;
  33.     prev_unit,next_unit : word;
  34.     in_interface : boolean;
  35.   end;
  36.  
  37.   unit_list_ptr = ^unit_list_rec;
  38.   unit_list_rec = record
  39.     name : string;
  40.     path : string;
  41.     obj_list : list_ptr;
  42.     proc_list : proc_list_ptr;
  43.     own_record : word;
  44.     checksum : word;
  45.     buffer     : byte_array_ptr;
  46.     has_symbols : boolean;
  47.   end;
  48.  
  49.   tpl_item_ptr = ^tpl_item_rec;
  50.   tpl_item_rec = record
  51.     buffer : byte_array_ptr;
  52.     size : word;
  53.     next : tpl_item_ptr;
  54.   end;
  55.  
  56.   tpl_list_ptr = ^tpl_list_rec;
  57.   tpl_list_rec = record
  58.     path : string;
  59.     first : tpl_item_ptr;
  60.   end;
  61.  
  62.   obj_ptr = ^obj_rec;
  63.   obj_rec = record
  64.     next_obj: word;  { in case of a hash collision }
  65.     obj_type : byte;
  66.     name: string;
  67.   end;
  68.  
  69. var
  70.   hash_table : hash_ptr;
  71.  
  72.   unit_list : array[1..255] of unit_list_ptr;
  73.   num_known : word;
  74.  
  75.   tpl_buffer : tpl_list_rec;
  76.  
  77.   procedure build_list(var obj_list:list_ptr;
  78.                          buffer:byte_array_ptr;
  79.                          hash_table:hash_ptr);
  80.   procedure destroy_list(obj_list:list_ptr);
  81.  
  82.   procedure add_unit(const objname:string;info:unit_ptr);
  83.   function  get_unit(unit_ofs:word):unit_list_ptr;
  84.   function  get_unit_buffer(buffer:pointer;unit_ofs:word):unit_list_ptr;
  85.   function  get_unit_name(unit_ofs:word):String;
  86.   function  get_unit_by_name(const name:string):unit_list_ptr;
  87.   function  get_unit_num(name:string):word;
  88.  
  89.   procedure loadtpl;
  90.   procedure ReadPathFile(var path:string;var Header:header_ptr);
  91.  
  92. implementation
  93.  
  94.   procedure build_list(var obj_list:list_ptr;
  95.                          buffer:byte_array_ptr;
  96.                          hash_table:hash_ptr);
  97.   var
  98.     i,j,t:word;
  99.     current,new_entry : list_ptr;
  100.     obj : obj_ptr;
  101.   begin
  102.     new(obj_list);
  103.     with obj_list^ do
  104.     begin
  105.       offset := $ffff;     { set up a sentinel record }
  106.       next := nil;
  107.     end;
  108.  
  109.     with hash_table^ do
  110.       for i := 0 to byte_len div 2 do
  111.         if table[i] <> 0 then
  112.         begin
  113.           t := table[i];
  114.           repeat
  115.             current := obj_list;
  116.             while t > current^.offset do
  117.               current := current^.next;
  118.             new(new_entry);
  119.             new_entry^ := current^;
  120.             current^.offset := t;
  121.             current^.hash := i;
  122.             current^.next := new_entry;
  123.              obj := add_only_offset(buffer,t);
  124.              { get the next object... }
  125.             t := obj^.next_obj;
  126.           until t = 0;
  127.         end;
  128.   end;
  129.  
  130.   procedure destroy_list(obj_list:list_ptr);
  131.   var aux:list_ptr;
  132.   begin
  133.     while obj_list<>nil do
  134.     begin
  135.       aux:=obj_list;
  136.       obj_list:=obj_list^.next;
  137.       dispose(aux);
  138.     end;
  139.   end;
  140.  
  141.   procedure ReadPathFile(var path:string;var Header:header_ptr);
  142.   var dir,unit_dirs:string;
  143.       i:integer;
  144.   begin
  145.     header:=nil;
  146.     read_file(path,pointer(header),0,sizeof(header^));
  147.     if header = nil then
  148.     begin
  149.       unit_dirs:=uses_path;
  150.       while (unit_dirs<>'') and (header=nil) do
  151.       begin
  152.         i:=pos(';',unit_dirs);
  153.         if i=0 then
  154.           i:=length(unit_dirs)+1;
  155.         dir := copy(unit_dirs,1,i-1);
  156.         unit_dirs := copy(unit_dirs,i+1,255);
  157.         if dir[length(dir)] <> '\' then
  158.           dir := dir + '\';
  159.         read_file(dir+path,pointer(header),0,sizeof(header^));
  160.       end;
  161.       if header<>nil then
  162.         path:=dir+path;
  163.     end;
  164.   end;
  165.  
  166.   procedure add_unit(const objname:string;info : unit_ptr);
  167.   var
  168.     size,total:word;
  169.     header:header_ptr;
  170.     unit_obj:obj_ptr;
  171.     junk : pointer;
  172.     obj_info : unit_ptr;
  173.     info_ofs,offset : word;
  174.     tpl_item : tpl_item_ptr;
  175.  
  176.   procedure load_buffer;
  177.   var i:integer;
  178.   begin
  179.     with unit_list[num_known]^ do
  180.     begin
  181.       path := objname+unit_ext;
  182.       ReadPathFile(path,header);
  183.       if header <> nil then
  184.       begin
  185.         if header^.file_id <> tpu_file_id then
  186.         begin
  187.           HaltError('Error:  file '+path+' is not a TP '+
  188. {$IFDEF UNIT60}
  189.            '6.0'
  190. {$ELSE}
  191.            '7.0'
  192. {$ENDIF}
  193.                    +' .TPU file!');
  194.         end;
  195.         read_file(path,pointer(buffer),0,header^.sym_size);
  196.         if buffer <> nil then
  197.         begin
  198.           has_symbols := true;
  199.           header:=header_ptr(buffer);
  200.         end;
  201.         exit;
  202.       end;
  203.       path := '';
  204.       tpl_item := tpl_buffer.first;
  205.       while tpl_item<>nil do
  206.       begin
  207.         header := header_ptr(tpl_item^.buffer);
  208.         if (header^.file_id <> tpu_file_id) then
  209.         begin
  210.           HaltError('Error searching '+tpl_name+'.  It is not a TP library!');
  211.         end;
  212.         unit_obj := add_only_offset(header,header^.ofs_this_unit);
  213.         if upper(unit_obj^.name) = upper(objname) then
  214.         begin
  215.           buffer := pointer(header);
  216.           has_symbols := true;
  217.           exit;
  218.         end;
  219.         tpl_item:=tpl_item^.next;
  220.       end;
  221.       WriteOutput('Warning:  Can''t find unit '+objname);
  222.     end;
  223.   end;
  224.  
  225.   var
  226.     existing : unit_list_ptr;
  227.     D: DirStr;
  228.     N: NameStr;
  229.     E: ExtStr;
  230.   begin
  231.     existing := get_unit_by_name(objname);
  232.     if existing <> nil then
  233.       with existing^ do
  234.       begin
  235.         if   (info <> nil)
  236.          and (existing^.buffer <> nil)
  237.          and (checksum <> info^.checksum) then
  238.         begin
  239.           writeln('Warning:  checksum for unit ',name,' is ',hexword(checksum),' in ',
  240.                   path);
  241.           has_symbols := false;
  242.           freemem(buffer,header^.sym_size);
  243.           buffer := nil;
  244.         end;
  245.         exit;
  246.       end;
  247.  
  248.     inc(num_known);
  249.     new(unit_list[num_known]);
  250.     with unit_list[num_known]^ do
  251.     begin
  252.       name := upper(objname);
  253.       obj_list := nil;
  254.       proc_list := nil;
  255.       buffer := nil;
  256.       has_symbols := false;
  257.       load_buffer;
  258.       if has_symbols then
  259.       begin
  260.         FSplit(name, D, N, E);
  261.         name:=N;
  262.         own_record := header_ptr(buffer)^.ofs_this_unit;
  263.         inc(own_record,
  264.             4+length(obj_rec(add_only_offset(buffer,own_record)^).name));
  265.         checksum := unit_ptr(add_only_offset(buffer,own_record))^.checksum;
  266.         { add the uses units to the unit_list }
  267.         offset := header_ptr(buffer)^.ofs_this_unit;
  268.         while offset <> 0 do
  269.         begin
  270.           unit_obj := add_only_offset(buffer,offset);
  271.           info_ofs := sizeof(obj_rec)-sizeof(string)+1+length(unit_obj^.name);
  272.           obj_info := add_only_offset(buffer,offset+info_ofs);
  273.           add_unit(unit_obj^.name,nil);
  274.           obj_info^.target := get_unit_num(unit_obj^.name);
  275.           offset := obj_info^.next_unit;
  276.         end;
  277.       end;
  278.  
  279.     end;
  280.   end;
  281.  
  282.   function get_unit(unit_ofs:word):unit_list_ptr;
  283.   var
  284.     the_unit : unit_ptr;
  285.   begin
  286.     if unit_ofs > unit_list[1]^.own_record then
  287.     begin
  288.       the_unit := add_only_offset(buffer,unit_ofs);
  289.       get_unit := unit_list[the_unit^.target];
  290.     end
  291.     else
  292.       get_unit := unit_list[1];
  293.   end;
  294.  
  295.   function  get_unit_name(unit_ofs:word):String;
  296.   var
  297.     the_unit : unit_ptr;
  298.   begin
  299.     if unit_ofs > unit_list[1]^.own_record then
  300.     begin
  301.       the_unit := add_only_offset(buffer,unit_ofs);
  302.       get_unit_name := unit_list[the_unit^.target]^.name;
  303.     end
  304.     else
  305.       get_unit_name := unit_list[1]^.name;
  306.   end;
  307.  
  308.   function get_unit_buffer(buffer:pointer;unit_ofs:word):unit_list_ptr;
  309.   var
  310.     the_unit : unit_ptr;
  311.   begin
  312.     the_unit := add_only_offset(buffer,unit_ofs);
  313.     get_unit_buffer := unit_list[the_unit^.target];
  314.   end;
  315.  
  316.   function get_unit_by_name(const name:string):unit_list_ptr;
  317.   var
  318.     i : word;
  319.   begin
  320.     i := get_unit_num(name);
  321.     if i <> 0 then
  322.       get_unit_by_name := unit_list[i]
  323.     else
  324.       get_unit_by_name := nil;
  325.   end;
  326.  
  327.   function get_unit_num(name:string):word;
  328.   var
  329.     i : word;
  330.   begin
  331.     name:=upper(name);
  332.     for i:=1 to num_known do
  333.       if unit_list[i]^.name = name then
  334.       begin
  335.         get_unit_num := i;
  336.         exit;
  337.       end;
  338.     get_unit_num := 0;
  339.   end;
  340.  
  341.   procedure LoadTpl;
  342.   var
  343.     total:longint;
  344.     header:header_ptr;
  345.     i : integer;
  346.  
  347.   procedure InsertToList(offset:longint;size:word);
  348.   var Aux:tpl_item_ptr;
  349.   begin
  350.     Aux:=New(tpl_item_ptr);
  351.     Aux^.Size:=size;
  352.     read_file(tpl_buffer.path,pointer(Aux^.buffer),offset,size);
  353.  
  354.     Aux^.Next:=tpl_buffer.First;
  355.     tpl_buffer.First:=Aux;
  356.   end;
  357.  
  358.   begin
  359.     with tpl_buffer do
  360.     begin
  361.       path := tpl_name;
  362.       first := nil;
  363.       total := 0;
  364.       ReadPathFile(path,header);
  365.       if header <> nil then
  366.       begin
  367.         while header<>nil do
  368.         begin
  369.           if header^.file_id<>tpu_file_id then
  370.           begin
  371.             WriteOutput('Warning:  '+path+' versiom mismatch.');
  372.             exit;
  373.           end;
  374.  
  375.           InsertToList(total,header^.sym_size);
  376.           freemem(header,sizeof(header^));
  377.  
  378.           header:=header_ptr(First^.Buffer);
  379.           Inc(total,
  380.                   roundup(header^.sym_size,16)
  381. {$IFNDEF UNIT60}
  382.                  +roundup(header^.browser_size,16)
  383. {$ENDIF}
  384.                  +roundup(header^.code_size,16)
  385.                  +roundup(header^.reloc_size,16)
  386.                  +roundup(header^.const_size,16)
  387.                  +roundup(header^.const_reloc_size,16));
  388.           read_file(path,pointer(header),total,sizeof(header^));
  389.         end;
  390.       end;
  391.     end;
  392.   end;
  393. end.
  394.  
  395.